package stuttgart.uni.locationtracker;

import android.app.ActionBar;
import android.app.FragmentTransaction;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.Menu;


public class LocationTrackerActivity extends FragmentActivity implements
		ActionBar.TabListener {

	private final String STATE_IS_RUNNING = "running";
	
	public IRemoteService mService = null;

	/**
	 * The {@link android.support.v4.view.PagerAdapter} that will provide
	 * fragments for each of the sections. We use a
	 * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
	 * will keep every loaded fragment in memory. If this becomes too memory
	 * intensive, it may be best to switch to a
	 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
	 */
	private SectionsPagerAdapter mSectionsPagerAdapter;
	private ActionBar actionBar;

	/**
	 * The {@link ViewPager} that will host the section contents.
	 */
	private ViewPager mViewPager;
	
	public static ConnectFragment connectFragment;
	public static StatusFragment statusFragment;
	public static FriendlistFragment friendlistFragment;
	public static boolean running = false;
	


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_location_tracker);
		
		mSectionsPagerAdapter = null;
		actionBar = null;
		connectFragment =null;
		statusFragment = null;
		friendlistFragment=null;
		
		
		Log.d("LocationTrackerActivity","LocationTrackerActivity onCreate");
		
		connectFragment = new ConnectFragment();
		statusFragment = new StatusFragment();
		friendlistFragment = new FriendlistFragment();

		// Set up the action bar.
		actionBar = getActionBar();
		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

		// Create the adapter that will return a fragment for each of the three
		// primary sections of the app.
		mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

		// Set up the ViewPager with the sections adapter.
		mViewPager = (ViewPager) findViewById(R.id.pager);
		mViewPager.setAdapter(mSectionsPagerAdapter);

		// When swiping between different sections, select the corresponding
		// tab. We can also use ActionBar.Tab#select() to do this if we have
		// a reference to the Tab.
		mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
			@Override
			public void onPageSelected(int position) {
				actionBar.setSelectedNavigationItem(position);
			}
		});

		// For each of the sections in the app, add a tab to the action bar.
		for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
			// Create a tab with text corresponding to the page title defined by
			// the adapter. Also specify this Activity object, which implements
			// the TabListener interface, as the callback (listener) for when
			// this tab is selected.
			actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this));
		}
		
		//recreate last content of TextViews if they have one
        if(savedInstanceState != null){
        	 running = savedInstanceState.getBoolean(STATE_IS_RUNNING);
        }
		
        if(running){
        	
        	running = bindService(new Intent(this,LocationTrackerService.class),mConnection, Context.BIND_AUTO_CREATE);
        }
	}
	
	@Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        
        savedInstanceState.putBoolean(STATE_IS_RUNNING, running);
        
        // Call the superclass so it can save the view hierarchy state
        super.onSaveInstanceState(savedInstanceState);
    }

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_location_tracker, menu);
		return false;
	}

	@Override
	public void onTabSelected(ActionBar.Tab tab,FragmentTransaction fragmentTransaction) {
		// When the given tab is selected, switch to the corresponding page in
		// the ViewPager.
		if(tab.getPosition()==2){
			if(running){
				try {
					mService.requestFriendListUpdate();
				} catch (RemoteException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		mViewPager.setCurrentItem(tab.getPosition());
	}

	@Override
	public void onTabUnselected(ActionBar.Tab tab,FragmentTransaction fragmentTransaction) {
	}

	@Override
	public void onTabReselected(ActionBar.Tab tab,FragmentTransaction fragmentTransaction) {
	}
	
	@Override
	protected void onDestroy() {
		if(running){
			try {
				mService.unregisterCallback(mCallback);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			unbindService(mConnection);
		}
		if(isFinishing()){
			stopService(new Intent(this,LocationTrackerService.class));
		}
		super.onDestroy();
	}

	/**
	 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
	 * one of the sections/tabs/pages.
	 */
	public class SectionsPagerAdapter extends FragmentPagerAdapter {

		public SectionsPagerAdapter(FragmentManager fm) {
			super(fm);
		}

		@Override
		public Fragment getItem(int position) {
		
			if(position==0){
				return connectFragment;
			}
			
			if(position==1){
				return statusFragment;
			}
			
			if(position==2){
				return friendlistFragment;
			}
			return connectFragment;
			
		}

		@Override
		public int getCount() {
			// Show 3 total pages.
			return 3;
		}

		@Override
		public CharSequence getPageTitle(int position) {
			switch (position) {
			case 0:
				return getString(R.string.title_section1).toUpperCase();
			case 1:
				return getString(R.string.title_section2).toUpperCase();
			case 2:
				return getString(R.string.title_section3).toUpperCase();
			}
			return null;
		}
	}


	// Things for Service Connection

	/* ServiceConnection connects to a service when started */
	public ServiceConnection mConnection = new ServiceConnection() {

		public void onServiceConnected(ComponentName className, IBinder service) {
			mService = IRemoteService.Stub.asInterface(service);

			try {
				mService.registerCallback(mCallback);
			} catch (RemoteException e) {
				Log.d("PedometerActivity","RemoteException in onServiceConnected");
			}
			
		}

		public void onServiceDisconnected(ComponentName className) {
			mService = null;
		}
	};

	// make it possible to start User Interface refresh from service
	private   IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {

		public void updateOwnValues(TrackingData trackingData) throws RemoteException {
			runOnUiThread(new UpdateOwnValuesRunnable(trackingData));
		}

		public void updateFriendValues(TrackingData trackingData, float distanceToFriend) throws RemoteException  {
			runOnUiThread(new UpdateFriendValuesRunnable(trackingData, distanceToFriend));
		}

		public void updateFriendList(FriendList friendList)throws RemoteException  {
			runOnUiThread(new UpdateFriendListRunnable(friendList));
		}

		@Override
		public void updatePacketReductionRatio(double packetReductionRatio) throws RemoteException {
			runOnUiThread(new UpdatePacketReductionRatioRunnable(packetReductionRatio));
		}
	};
	
	private  class UpdateOwnValuesRunnable implements Runnable{

		TrackingData trackingData;
		
		public UpdateOwnValuesRunnable(TrackingData trackingData){
			this.trackingData = trackingData;
		}
		
		@Override
		public void run() {
			statusFragment.updateOwnValues(trackingData.getUsername(),
					trackingData.getLatitude(),
					trackingData.getLongitude(),
					trackingData.getSpeed(),
					trackingData.getBearing());
		}
		
	}
	private  class UpdateFriendValuesRunnable implements Runnable{

		TrackingData trackingData;
		float distanceToFriend;
		
		public UpdateFriendValuesRunnable(TrackingData trackingData, float distanceToFriend){
			this.trackingData = trackingData;
			this.distanceToFriend = distanceToFriend;
		}
		
		@Override
		public void run() {
			statusFragment.updateFriendValues(trackingData.getUsername(),
					trackingData.getLatitude(),
					trackingData.getLongitude(),
					trackingData.getSpeed(),
					trackingData.getBearing(),
					distanceToFriend);
		}
		
	}
	private  class UpdateFriendListRunnable implements Runnable{
		
		FriendList friendList;
		
		public UpdateFriendListRunnable(FriendList friendList){
			this.friendList = friendList;
		}

		@Override
		public void run() {
			friendlistFragment.updateFriendList(friendList);
		}
	}
	
	private  class UpdatePacketReductionRatioRunnable implements Runnable{
		
		double packetReductionRatio;
		
		public UpdatePacketReductionRatioRunnable(double packetReductionRatio){
			this.packetReductionRatio = packetReductionRatio;
		}

		@Override
		public void run() {
			connectFragment.updatePacketReductionRatio(packetReductionRatio);
		}
		
	}
}
